package com.jdrx.sw.sewage.dubbo.rpc;

import com.jdrx.platform.dubbo.common.beans.DubboRpcBean;
import com.jdrx.sw.sewage.common.constant.Constant;

import org.apache.commons.lang3.StringUtils;
import org.apache.dubbo.common.constants.CommonConstants;
import org.apache.dubbo.common.extension.Activate;
import org.apache.dubbo.rpc.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import java.util.Objects;

/**
 * 用于配置配置 Dubbo 调用时, 透传请求信息配置
 * 参考 META-INF\META-INF.dubbo\org.apache.META-INF.dubbo.rpc.Filter
 * <p>
 * Create by dengfan at 2019/9/18 0018 17:24
 */
public class DubboRpcFilterConfig {

	private final static Logger log = LoggerFactory.getLogger(DubboRpcFilterConfig.class);

	/**
	 * 透传 header 头
	 */
	@Activate(group = CommonConstants.CONSUMER)
	public static class RequestHeaderTransportFilter implements Filter {
		@Override
		public Result invoke(Invoker<?> invoker, Invocation invocation) throws RpcException {
			try {
				log.debug("远程 META-INF.dubbo 接口调用开始");
				String tenantId = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest().getHeader(Constant.TENANT_ID);
				Object[] args = invocation.getArguments();
				DubboRpcBean request = (DubboRpcBean) args[0];
				if(StringUtils.isBlank(tenantId) || StringUtils.equals(tenantId, "null")) {
					tenantId = String.valueOf(request.getHeader(Constant.TENANT_ID));
				}
				request.getBuilder().setHeader(Constant.TENANT_ID, tenantId);
				log.debug("获取到的租户id={}", tenantId);
				return invoker.invoke(invocation);
			} catch (Exception e) {
				log.error("无法调用dubbo请求,", e);
				throw new RpcException("无法调用远程接口");
			}
		}
	}

	/**
	 * 接收header头
	 */
	@Activate(group = CommonConstants.PROVIDER)
	public static class RequestHeaderAcceptFilter implements Filter {
		@Override
		public Result invoke(Invoker<?> invoker, Invocation invocation) throws RpcException {
			log.debug("META-INF.dubbo recevie tenantId header.");
			Object[] args = invocation.getArguments();
			DubboRpcBean request = (DubboRpcBean) args[0];
			String tenantId = (String) request.getHeader(Constant.TENANT_ID);
			log.debug("select tenantId - > {}", tenantId);
			if (Objects.nonNull(tenantId)) {
				RpcContext.getContext().setAttachment(Constant.TENANT_ID, tenantId);
			} else {
				throw new RpcException(" http header tenantId not found, tenantId select error");
			}
			return invoker.invoke(invocation);
		}
	}
}